﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using LDSCore.Properties;
using LDSCore.Result;

public static class Expand
{
    /// <summary>
    /// 输出内部编码
    /// </summary>
    /// <param name="code">结果码</param>
    /// <returns></returns>
    public static string ToCode(this ResultCode code)
    {
        return "MSG" + (int)code;
    }

    /// <summary>
    /// 输出用户提示信息
    /// </summary>
    /// <param name="code">结果码</param>
    /// <returns></returns>
    public static string ToMessage(this ResultCode code)
    {
        return ResultCodeResources.ResourceManager.GetString(code.ToString());
    }

    /// <summary>
    /// 返回枚举类型的中文描述 DescriptionAttribute 指定的名字
    /// </summary>
    /// <typeparam name="TEnum"></typeparam>
    /// <param name="Enum"></param>
    /// <returns></returns>
    public static string Description<TEnum>(this TEnum Enum) where TEnum : struct
    {
        var em = Enum.ToString();
        FieldInfo fieldInfo = Enum.GetType().GetField(em);
        if (fieldInfo == null) return em;
        var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
        if (attributes.Length < 1) return em;
        return attributes[0].Description;
    }

    /// <summary>
    /// 将枚举以字典的形式返回
    /// </summary>
    /// <typeparam name="TEnum"></typeparam>
    /// <param name="enumObj"></param>
    /// <returns></returns>
    public static Dictionary<int, string> ToList<TEnum>(this TEnum enumObj) where TEnum : struct
    {
        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                     select new KeyValuePair<int, string>(e.GetHashCode(), e.Description());
        return values.ToDictionary(a => a.Key, b => b.Value);
    }

    /// <summary>
    /// 从字节流创建对象
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="t">对象实体</param>
    /// <param name="bytes">字节流</param>
    /// <returns>返回转换后的对象</returns>
    public static T FromBytes<T>(this T t, byte[] bytes) where T : class
    {
        return FromBytes(t, bytes, 0);
    }
    
    /// <summary>
    /// 从字节流创建对象
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="t">对象实体</param>
    /// <param name="bytes">字节流</param>
    /// <param name="startIndex">转换开始位置</param>
    /// <returns>返回转换后的对象</returns>
    public static T FromBytes<T>(this T t, byte[] bytes, int startIndex) where T : class
    {
        Type type = typeof(T);

        //得到结构体的大小
        int size = Marshal.SizeOf(type);
        //byte数组长度小于结构体的大小
        if (size > (bytes.Length - startIndex))
        {
            //返回空
            return null;
        }
        //分配结构体大小的内存空间
        var structPtr = Marshal.AllocHGlobal(size);
        //将byte数组拷到分配好的内存空间
        Marshal.Copy(bytes, startIndex, structPtr, size);
        //将内存空间转换为目标结构体
        var obj = (T)Marshal.PtrToStructure(structPtr, type);
        //释放内存空间
        Marshal.FreeHGlobal(structPtr);
        //返回结构体
        return obj;
    }

    /// <summary>
    /// 将对象转换为字节流
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="t">对象实体</param>
    /// <returns>返回转换后的字节流</returns>
    public static byte[] ToBytes<T>(this T t) where T : class
    {
        //得到结构体的大小
        var size = Marshal.SizeOf(t);
        //创建byte数组
        var bytes = new byte[size];
        //分配结构体大小的内存空间
        var structPtr = Marshal.AllocHGlobal(size);
        //将结构体拷到分配好的内存空间
        Marshal.StructureToPtr(t, structPtr, false);
        //从内存空间拷到byte数组
        Marshal.Copy(structPtr, bytes, 0, size);
        //释放内存空间
        Marshal.FreeHGlobal(structPtr);
        //返回byte数组
        return bytes;
    }
}